#include "bsl_params.h"
#include "bsl_errno.h"
#include "bsl_err_internal.h"
#include "crypt_algid.h"
#include "crypt_errno.h"
#include "crypt_rsa.h"
#include "crypt_eal_md.h"
#include "rsa_local.h"
#include "crypt_utils.h"
#include "securec.h"

#include "wd.h"
#include "wd_rsa.h"
#include "wd_bmm.h"

#include "rsa.h"


#define RSA_BLOCK_NUM 16
#define RSA_BLOCK_SIZE 4096

static void hpre_rsa_cb(const void *message, void *tag)
{
    if (!message || !tag) {
        return;
    }
    struct wcrypto_rsa_msg *msg = (struct wcrypto_rsa_msg *)message;
    KAE_RSA_Ctx* ctx = (KAE_RSA_Ctx* )tag;
    ctx->opData.out = msg->out;
    ctx->opData.out_bytes = msg->out_bytes;
    ctx->opData.status = msg->result;
}

RSA_Para* KAE_RSA_NewParaFromBits(uint32_t bits)
{
    RSA_Para* newPara = (RSA_Para*) malloc(sizeof(RSA_Para));

    newPara->e = BN_Create(bits);
    newPara->d = BN_Create(bits);
    newPara->n = BN_Create(bits);
    newPara->p = BN_Create(bits);
    newPara->q = BN_Create(bits);
    newPara->dP = BN_Create(bits);
    newPara->dQ = BN_Create(bits);
    newPara->qInv = BN_Create(bits);

    if (newPara == NULL || newPara->e == NULL || newPara->p == NULL || newPara->q == NULL ||
        newPara->n == NULL || newPara->d == NULL || newPara->dP == NULL ||
        newPara->dQ == NULL || newPara->qInv == NULL) {
            KAE_RSA_FreePara(newPara);
            BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
            return NULL;
    }

    newPara->bits = bits;
    return newPara;
}

int32_t KAE_RSA_ParaCopy(RSA_Para* dst, RSA_Para* src)
{
    if (dst == NULL || src == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }
    dst->bits = src->bits;

    int32_t ret;
    GOTO_ERR_IF(BN_Copy(dst->n, src->n), ret);
    GOTO_ERR_IF(BN_Copy(dst->e, src->e), ret);
    GOTO_ERR_IF(BN_Copy(dst->d, src->d), ret);
    GOTO_ERR_IF(BN_Copy(dst->p, src->p), ret);
    GOTO_ERR_IF(BN_Copy(dst->q, src->q), ret);
    GOTO_ERR_IF(BN_Copy(dst->dP, src->dP), ret);
    GOTO_ERR_IF(BN_Copy(dst->dQ, src->dQ), ret);
    GOTO_ERR_IF(BN_Copy(dst->dP, src->dP), ret);
    GOTO_ERR_IF(BN_Copy(dst->qInv, src->qInv), ret);
ERR:
    return ret;
}

KAE_RSA_Ctx* KAE_RSA_NewCtx()
{
    KAE_RSA_Ctx* ctx = (KAE_RSA_Ctx*) malloc(sizeof(KAE_RSA_Ctx));
    if (ctx == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
        return NULL;
    }

    memset(ctx, 0, sizeof(KAE_RSA_Ctx));

    ctx->queue.capa.alg = "rsa";
    wd_request_queue(&(ctx->queue));

    struct wd_blkpool_setup pool_setup;
    memset(&pool_setup, 0, sizeof(pool_setup));
    pool_setup.block_size = RSA_BLOCK_SIZE;
    pool_setup.block_num = RSA_BLOCK_NUM;
    pool_setup.align_size = 64;
    ctx->pool = wd_blkpool_create(&ctx->queue, &pool_setup);
    ctx->padType = RSA_NO_PAD;
    ctx->rsaCtx = NULL;

    return ctx;
}

int32_t KAE_RSA_SetPara(KAE_RSA_Ctx* ctx, const BSL_Param *para)
{
    if (ctx == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }
    RSA_Para *rsaPara = KAE_RSA_NewPara(para);
    if (rsaPara == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_NEW_PARA_FAIL);
        return CRYPT_EAL_ERR_NEW_PARA_FAIL;
    }
    int32_t ret = IsRSASetParaVaild(ctx, rsaPara);
    if (ret != CRYPT_SUCCESS) {
        BSL_ERR_PUSH_ERROR(ret);
        KAE_RSA_FreePara(rsaPara);
        return ret;
    }

    KAE_RSA_FreePara(ctx->para);

    if (ctx->rsaCtx != NULL) {
        wcrypto_del_rsa_ctx(ctx->rsaCtx);
    }

    ctx->para = rsaPara;

    ctx->setup.key_bits = rsaPara->bits;
    ctx->setup.cb = (wcrypto_cb) hpre_rsa_cb;
    ctx->setup.is_crt = 1;
    ctx->setup.br.alloc = (void *) wd_alloc_blk;
    ctx->setup.br.free = (void *) wd_free_blk;
    ctx->setup.br.iova_map = (void *) wd_blk_iova_map;
    ctx->setup.br.iova_unmap = (void *) wd_blk_iova_unmap;
    ctx->setup.br.usr = ctx->pool;
    return CRYPT_SUCCESS;
}

int32_t KAE_RSA_Store2Para(KAE_RSA_Ctx* ctx)
{
    struct wd_dtb wd_d;
    struct wd_dtb wd_n;
    struct wd_dtb wd_qinv;
    struct wd_dtb wd_dq;
    struct wd_dtb wd_dp;

    struct wcrypto_rsa_kg_out *out = (struct wcrypto_rsa_kg_out *) ctx->opData.out;
    wcrypto_get_rsa_kg_out_params(out, &wd_d, &wd_n);
    wcrypto_get_rsa_kg_out_crt_params(out, &wd_qinv, &wd_dq, &wd_dp);

    int32_t ret;
    uint32_t key_bits = ctx->para->bits;
    uint32_t key_size = key_bits >> 3;
    GOTO_ERR_IF(BN_Bin2Bn(ctx->para->n, wd_n.data, key_size), ret);
    GOTO_ERR_IF(BN_Bin2Bn(ctx->para->d, wd_d.data, key_size), ret);
    GOTO_ERR_IF(BN_Bin2Bn(ctx->para->qInv, wd_qinv.data, wd_qinv.dsize), ret);
    GOTO_ERR_IF(BN_Bin2Bn(ctx->para->dP, wd_dp.data, wd_dp.dsize), ret);
    GOTO_ERR_IF(BN_Bin2Bn(ctx->para->dQ, wd_dq.data, wd_dq.dsize), ret);
ERR:
    return ret;
}

int32_t KAE_RSA_SetPub(KAE_RSA_Ctx* ctx, const BSL_Param *para)
{
    BSL_Param *ncPara = (BSL_Param *) para;
    BSL_Param *n    = BSL_PARAM_FindParam(ncPara, CRYPT_PARAM_RSA_N);
    BSL_Param *e    = BSL_PARAM_FindParam(ncPara, CRYPT_PARAM_RSA_E);

    if (PARAMISNULL(n) || PARAMISNULL(e)) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }

    int32_t ret;
    BN_BigNum* newN = BN_Create(ctx->para->bits);
    BN_BigNum* newE = BN_Create(ctx->para->bits);
    GOTO_ERR_IF(BN_Bin2Bn(newN, (uint8_t *) n->value, n->valueLen), ret);

    uint32_t bnBits = BN_Bits(newN);
    if (bnBits > RSA_MAX_MODULUS_BITS || bnBits < RSA_MIN_MODULUS_BITS) {
        ret = CRYPT_RSA_ERR_KEY_BITS;
        BSL_ERR_PUSH_ERROR(ret);
        goto ERR;
    }

    GOTO_ERR_IF(BN_Bin2Bn(newE, (uint8_t *) e->value, e->valueLen), ret);

    if (BN_Cmp(newN, newE) <= 0 || BN_IsZero(newE) || BN_IsOne(newE)) {
        ret = CRYPT_RSA_ERR_INPUT_VALUE;
        BSL_ERR_PUSH_ERROR(ret);
        goto ERR;
    }

    BN_Destroy(ctx->para->n);
    BN_Destroy(ctx->para->e);
    ctx->para->n = newN;
    ctx->para->e = newE;
    return CRYPT_SUCCESS;
ERR:
    BN_Destroy(newN);
    BN_Destroy(newE);
    return ret;
}

int32_t KAE_RSA_SetPrv(KAE_RSA_Ctx* ctx, const BSL_Param *para)
{
    BSL_Param *ncPara = (BSL_Param *) para;
    BSL_Param *n    = BSL_PARAM_FindParam(ncPara, CRYPT_PARAM_RSA_N);
    BSL_Param *d    = BSL_PARAM_FindParam(ncPara, CRYPT_PARAM_RSA_D);
    BSL_Param *e    = BSL_PARAM_FindParam(ncPara, CRYPT_PARAM_RSA_E);
    BSL_Param *p    = BSL_PARAM_FindParam(ncPara, CRYPT_PARAM_RSA_P);
    BSL_Param *q    = BSL_PARAM_FindParam(ncPara, CRYPT_PARAM_RSA_Q);
    BSL_Param *dP   = BSL_PARAM_FindParam(ncPara, CRYPT_PARAM_RSA_DP);
    BSL_Param *dQ   = BSL_PARAM_FindParam(ncPara, CRYPT_PARAM_RSA_DQ);
    BSL_Param *qInv = BSL_PARAM_FindParam(ncPara, CRYPT_PARAM_RSA_QINV);

    if (PARAMISNULL(n) || n->valueLen == 0 || PARAMISNULL(d)) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }
    if (n->valueLen > RSA_MAX_MODULUS_LEN) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_ERR_KEY_BITS);
        return CRYPT_RSA_ERR_KEY_BITS;
    }
    // prv->p\q and prv->dP\dQ\qInv must be both empty or not.
    // If prv->p is empty, prv->dP must be empty.
    if ((PARAMISNULL(p) != PARAMISNULL(q)) || (PARAMISNULL(p) && !PARAMISNULL(dP))) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_NO_KEY_INFO);
        return CRYPT_RSA_NO_KEY_INFO;
    }
    if ((PARAMISNULL(dP) || PARAMISNULL(dQ) || PARAMISNULL(qInv)) &&
        (!PARAMISNULL(dP) || !PARAMISNULL(dQ) || !PARAMISNULL(qInv))) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_NO_KEY_INFO);
        return CRYPT_RSA_NO_KEY_INFO;
    }

    uint32_t bnBytes = n->valueLen;
    if (d->valueLen > bnBytes || p->valueLen > bnBytes || q->valueLen > bnBytes) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_ERR_KEY_BITS);
        return CRYPT_RSA_ERR_KEY_BITS;
    }

    RSA_Para* newPara = KAE_RSA_NewParaFromBits(ctx->para->bits);
    if (newPara == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
        return CRYPT_MEM_ALLOC_FAIL;
    }

    int32_t ret = BN_Bin2Bn(newPara->n, n->value, n->valueLen);
    if (ret != CRYPT_SUCCESS) {
        BSL_ERR_PUSH_ERROR(ret);
        return ret;
    }
    uint32_t bnBits = BN_Bits(newPara->n);
    if (bnBits > RSA_MAX_MODULUS_BITS || bnBits < RSA_MIN_MODULUS_BITS) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_ERR_KEY_BITS);
        return CRYPT_RSA_ERR_KEY_BITS;
    }
    ret = BN_Bin2Bn(newPara->d, d->value, d->valueLen);
    if (ret != CRYPT_SUCCESS) {
        BSL_ERR_PUSH_ERROR(ret);
        return ret;
    }
    // d cannot be 0 or 1. The mathematical logic of e and d is that
    // d and e are reciprocal in mod((p-1) * (q-1)); When d is 1, e and d must be 1. When d is 0, e doesn't exist.
    if (BN_IsZero(newPara->d) || BN_IsOne(newPara->d)) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_ERR_INPUT_VALUE);
        return CRYPT_RSA_ERR_INPUT_VALUE;
    }
    if (BN_Cmp(newPara->n, newPara->d) <= 0) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_ERR_INPUT_VALUE);
        return CRYPT_RSA_ERR_INPUT_VALUE;
    }
    if (!PARAMISNULL(e)) {
        ret = BN_Bin2Bn(newPara->e, e->value, e->valueLen);
        if (ret != CRYPT_SUCCESS) {
            BSL_ERR_PUSH_ERROR(ret);
            return ret;
        }
        if (BN_Cmp(newPara->n, newPara->e) <= 0) {
            BSL_ERR_PUSH_ERROR(CRYPT_RSA_ERR_INPUT_VALUE);
            return CRYPT_RSA_ERR_INPUT_VALUE;
        }
    }
    if (!PARAMISNULL(p)) {
        GOTO_ERR_IF_EX(BN_Bin2Bn(newPara->p, p->value, p->valueLen), ret);
        GOTO_ERR_IF_EX(BN_Bin2Bn(newPara->q, q->value, q->valueLen), ret);
        if (BN_IsZero(newPara->p) == true || BN_IsZero(newPara->q) == true) {
            BSL_ERR_PUSH_ERROR(CRYPT_RSA_ERR_INPUT_VALUE);
            return CRYPT_RSA_ERR_INPUT_VALUE;
        }
        if (!PARAMISNULL(dP)) {
            GOTO_ERR_IF_EX(BN_Bin2Bn(newPara->dP, dP->value, dP->valueLen), ret);
            GOTO_ERR_IF_EX(BN_Bin2Bn(newPara->dQ, dQ->value, dQ->valueLen), ret);
            GOTO_ERR_IF_EX(BN_Bin2Bn(newPara->qInv, qInv->value, qInv->valueLen), ret);
        }
    }

    RSA_Para* oldPara = ctx->para;
    if (!PARAMISNULL(p) && PARAMISNULL(dP)) {
        ctx->para = newPara;
        ret = KAE_RSA_GenKey(ctx);
        if (ret != CRYPT_SUCCESS) {
            ctx->para = oldPara;
            goto ERR;
        }
    }
    ctx->para = newPara;
    KAE_RSA_FreePara(oldPara);
    return CRYPT_SUCCESS;
ERR:
    KAE_RSA_FreePara(newPara);
    return ret;
}

int32_t KAE_RSA_GetPub(KAE_RSA_Ctx* ctx, BSL_Param *para)
{
    BSL_Param *n    = BSL_PARAM_FindParam(para, CRYPT_PARAM_RSA_N);
    BSL_Param *e    = BSL_PARAM_FindParam(para, CRYPT_PARAM_RSA_E);

    if (PARAMISNULL(n) || PARAMISNULL(e)) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }

    int32_t ret;
    n->useLen = n->valueLen;
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->n, n->value, &(n->useLen)), ret);
    e->useLen = e->valueLen;
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->e, e->value, &(e->useLen)), ret);

    return CRYPT_SUCCESS;
ERR:
}

int32_t KAE_RSA_GetPrv(KAE_RSA_Ctx* ctx, BSL_Param *para)
{
    BSL_Param *n    = BSL_PARAM_FindParam(para, CRYPT_PARAM_RSA_N);
    BSL_Param *d    = BSL_PARAM_FindParam(para, CRYPT_PARAM_RSA_D);
    BSL_Param *e    = BSL_PARAM_FindParam(para, CRYPT_PARAM_RSA_E);
    BSL_Param *p    = BSL_PARAM_FindParam(para, CRYPT_PARAM_RSA_P);
    BSL_Param *q    = BSL_PARAM_FindParam(para, CRYPT_PARAM_RSA_Q);
    BSL_Param *dP   = BSL_PARAM_FindParam(para, CRYPT_PARAM_RSA_DP);
    BSL_Param *dQ   = BSL_PARAM_FindParam(para, CRYPT_PARAM_RSA_DQ);
    BSL_Param *qInv = BSL_PARAM_FindParam(para, CRYPT_PARAM_RSA_QINV);

    if ((PARAMISNULL(p) != PARAMISNULL(q)) ||
        ((PARAMISNULL(dP) || PARAMISNULL(dQ) || PARAMISNULL(qInv)) &&
         (!PARAMISNULL(dP) || !PARAMISNULL(dQ) || !PARAMISNULL(qInv))) ||
        (PARAMISNULL(p) && !PARAMISNULL(dP))) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }

    int32_t ret;
    n->useLen = n->valueLen;
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->n, n->value, &(n->useLen)), ret);
    d->useLen = d->valueLen;
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->d, d->value, &(d->useLen)), ret);
    if (!PARAMISNULL(e)) {
        e->useLen = e->valueLen;
        GOTO_ERR_IF(BN_Bn2Bin(ctx->para->e, e->value, &(e->useLen)), ret);
    }
    if (!PARAMISNULL(p)) {
        p->useLen = p->valueLen;
        GOTO_ERR_IF(BN_Bn2Bin(ctx->para->p, p->value, &(p->useLen)), ret);

        q->useLen = q->valueLen;
        GOTO_ERR_IF(BN_Bn2Bin(ctx->para->q, q->value, &(q->useLen)), ret);
    }
    if (!PARAMISNULL(dQ)) {
        dQ->useLen = dQ->valueLen;
        GOTO_ERR_IF(BN_Bn2Bin(ctx->para->dQ, dQ->value, &(dQ->useLen)), ret);
        dP->useLen = dP->valueLen;
        GOTO_ERR_IF(BN_Bn2Bin(ctx->para->dP, dP->value, &(dP->useLen)), ret);
        qInv->useLen = qInv->valueLen;
        GOTO_ERR_IF(BN_Bn2Bin(ctx->para->qInv, qInv->value, &(qInv->useLen)), ret);
    }
ERR:
    return ret;
}

KAE_RSA_Ctx* KAE_RSA_DupCtx(KAE_RSA_Ctx* ctx)
{
    if (ctx == NULL || ctx->para == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return NULL;
    }
    KAE_RSA_Ctx* newCtx = KAE_RSA_NewCtx();
    if (newCtx == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
        return NULL;
    }
    RSA_Para* newPara = KAE_RSA_NewParaFromBits(ctx->para->bits);
    if (newPara == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
        KAE_RSA_Free(newCtx);
        return NULL;
    }

    int32_t ret = KAE_RSA_ParaCopy(newPara, ctx->para);
    if (ret != CRYPT_SUCCESS) {
        BSL_ERR_PUSH_ERROR(ret);
        KAE_RSA_FreePara(newPara);
        KAE_RSA_Free(newCtx);
        return NULL;
    }

    return newCtx;
}

int32_t KAE_RSA_Cmp(const KAE_RSA_Ctx *a, const KAE_RSA_Ctx *b)
{
    if (a == NULL || b == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }

    if (a->para == NULL || b->para == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_NO_KEY_INFO);
        return CRYPT_RSA_NO_KEY_INFO;
    }

    if (BN_Cmp(a->para->n, b->para->n) != 0 || BN_Cmp(a->para->e, b->para->e)) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_PUBKEY_NOT_EQUAL);
        return CRYPT_RSA_PUBKEY_NOT_EQUAL;
    }
    return CRYPT_SUCCESS;
}

int32_t KAE_RSA_GetPad(KAE_RSA_Ctx* ctx, void *val, uint32_t len)
{
    RSA_PadType *valTmp = val;
    if (val == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }
    if (len != sizeof(int32_t)) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_SET_FLAG_LEN_ERROR);
        return CRYPT_RSA_SET_FLAG_LEN_ERROR;
    }
    *valTmp = ctx->padType;
    return CRYPT_SUCCESS;
}

int32_t KAE_RSA_SetPad(KAE_RSA_Ctx* ctx, void *val, uint32_t len)
{
    if (val == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }
    if (len != sizeof(int32_t)) {
        BSL_ERR_PUSH_ERROR(CRYPT_RSA_SET_FLAG_LEN_ERROR);
        return CRYPT_RSA_SET_FLAG_LEN_ERROR;
    }

    int32_t pad = *(const int32_t *)val;
    if (pad < EMSA_PKCSV15 || pad > RSA_NO_PAD) {
        BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
        return CRYPT_INVALID_ARG;
    }

    ctx->padType = pad;
    return CRYPT_SUCCESS;
}

int32_t KAE_RSA_Ctrl(KAE_RSA_Ctx* ctx, int32_t opt, void *val, uint32_t len)
{
    if (ctx == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }
    switch (opt) {
        case CRYPT_CTRL_GET_RSA_PADDING:
            return KAE_RSA_GetPad(ctx, val, len);
        case CRYPT_CTRL_SET_RSA_PADDING:
            return KAE_RSA_SetPad(ctx, val, len);
        default:
            BSL_ERR_PUSH_ERROR(CRYPT_RSA_CTRL_NOT_SUPPORT_ERROR);
            return CRYPT_RSA_CTRL_NOT_SUPPORT_ERROR;
    }
}

int32_t RsaFillPubKey(KAE_RSA_Ctx* ctx)
{
    struct wd_dtb *wd_e = NULL;
    struct wd_dtb *wd_n = NULL;

    wcrypto_get_rsa_pubkey(ctx->rsaCtx, &ctx->pubKey);
    wcrypto_get_rsa_pubkey_params(ctx->pubKey, &wd_e, &wd_n);

    int32_t ret;
    uint32_t bnBytes = ctx->para->bits >> 3;
    wd_n->dsize =  bnBytes;
    wd_e->dsize =  bnBytes;
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->n, (unsigned char *)wd_n->data, &(wd_n->dsize)), ret);
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->e, (unsigned char *)wd_e->data, &(wd_e->dsize)), ret);
ERR:
    return ret;
}

int32_t RsaFillPrvKeyNoCRT(KAE_RSA_Ctx* ctx)
{
    struct wd_dtb *wd_d = NULL;
    struct wd_dtb *wd_n = NULL;

    wcrypto_get_rsa_prikey(ctx->rsaCtx, &ctx->prvKey);
    wcrypto_get_rsa_prikey_params(ctx->prvKey, &wd_d, &wd_n);

    int32_t ret;
    uint32_t bnBytes = ctx->para->bits >> 3;
    wd_n->dsize =  bnBytes;
    wd_d->dsize =  bnBytes;
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->n, (unsigned char *)wd_n->data, &(wd_n->dsize)), ret);
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->d, (unsigned char *)wd_d->data, &(wd_d->dsize)), ret);
ERR:
    return ret;
}

int32_t RsaFillPrvKeyCRT(KAE_RSA_Ctx* ctx)
{
    struct wd_dtb *wd_dq;
    struct wd_dtb *wd_dp;
    struct wd_dtb *wd_q;
    struct wd_dtb *wd_p;
    struct wd_dtb *wd_qinv;

    wcrypto_get_rsa_prikey(ctx->rsaCtx, &ctx->prvKey);
    wcrypto_get_rsa_crt_prikey_params(ctx->prvKey, &wd_dq, &wd_dp, &wd_qinv, &wd_q, &wd_p);

    int32_t ret;
    uint32_t bnBytes = ctx->para->bits >> 3;
    wd_p->dsize =  bnBytes;
    wd_q->dsize =  bnBytes;
    wd_dp->dsize =  bnBytes;
    wd_dq->dsize =  bnBytes;
    wd_qinv->dsize =  bnBytes;

    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->p, (unsigned char *) wd_p->data, &(wd_p->dsize)), ret);

    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->q, (unsigned char *) wd_q->data, &(wd_q->dsize)), ret);
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->dP, (unsigned char *) wd_dp->data, &(wd_dp->dsize)), ret);
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->dQ, (unsigned char *) wd_dq->data, &(wd_dq->dsize)), ret);
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->qInv, (unsigned char *) wd_qinv->data, &(wd_qinv->dsize)), ret);
ERR:
    return ret;
}

int32_t KAE_RSA_GenKey(KAE_RSA_Ctx* ctx)
{
    int ret = KAE_RSA_Gen(ctx);
    if (ret != CRYPT_SUCCESS) {
        BSL_ERR_PUSH_ERROR(ret);
        return ret;
    }

    ctx->rsaCtx = wcrypto_create_rsa_ctx(&ctx->queue, &ctx->setup);

    struct wd_dtb *wd_e = NULL;
    struct wd_dtb *wd_p = NULL;
    struct wd_dtb *wd_q = NULL;

    wcrypto_get_rsa_pubkey(ctx->rsaCtx, &ctx->pubKey);
    wcrypto_get_rsa_pubkey_params(ctx->pubKey, &wd_e, NULL);
    wcrypto_get_rsa_prikey(ctx->rsaCtx, &ctx->prvKey);
    wcrypto_get_rsa_crt_prikey_params(ctx->prvKey, NULL, NULL, NULL, &wd_q, &wd_p);

    uint32_t bnBytes = ctx->para->bits >> 3;

    wd_e->dsize = bnBytes;
    wd_p->dsize = bnBytes;
    wd_q->dsize = bnBytes;
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->e, wd_e->data, &wd_e->dsize), ret);
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->p, wd_p->data, &wd_p->dsize), ret);
    GOTO_ERR_IF(BN_Bn2Bin(ctx->para->q, wd_q->data, &wd_q->dsize), ret);

    ctx->opData.op_type = WCRYPTO_RSA_GENKEY;
    ctx->opData.in_bytes = (ctx->para->bits) >> 3;
    ctx->opData.in = wcrypto_new_kg_in(ctx->rsaCtx, wd_e, wd_p, wd_q);
    ctx->opData.out = wcrypto_new_kg_out(ctx->rsaCtx);

    wcrypto_do_rsa(ctx->rsaCtx, &ctx->opData, NULL);
    GOTO_ERR_IF(KAE_RSA_Store2Para(ctx) != CRYPT_SUCCESS, ret);
    wd_free_blk(ctx->pool, ctx->opData.in);
    wd_free_blk(ctx->pool, ctx->opData.out);
    wcrypto_del_rsa_ctx(ctx->rsaCtx);
ERR:
    return ret;
}

int32_t KAE_RSA_SignData(KAE_RSA_Ctx* ctx, const uint8_t *data, uint32_t dataLen, uint8_t *sign, uint32_t *signLen)
{
    ctx->rsaCtx = wcrypto_create_rsa_ctx(&ctx->queue, &ctx->setup);
    RsaFillPubKey(ctx);
    ctx->setup.is_crt ? RsaFillPrvKeyCRT(ctx) : RsaFillPrvKeyNoCRT(ctx);

    ctx->opData.in_bytes = ctx->para->bits >> 3;
    ctx->opData.op_type = WCRYPTO_RSA_SIGN;
    ctx->opData.in  = wd_alloc_blk(ctx->pool);
    ctx->opData.out = wd_alloc_blk(ctx->pool);
    memcpy(ctx->opData.in, data, ctx->opData.in_bytes );
    wcrypto_do_rsa(ctx->rsaCtx, &ctx->opData, NULL);
    memcpy(sign, ctx->opData.out, ctx->opData.out_bytes);
    *signLen = ctx->opData.out_bytes;
    wd_free_blk(ctx->pool, ctx->opData.in);
    wd_free_blk(ctx->pool, ctx->opData.out);
    wcrypto_del_rsa_ctx(ctx->rsaCtx);
    return CRYPT_SUCCESS;
}

int32_t KAE_RSA_VerifyData(KAE_RSA_Ctx* ctx, const uint8_t *data, uint32_t dataLen, uint8_t *sign, uint32_t signLen)
{
    ctx->rsaCtx = wcrypto_create_rsa_ctx(&ctx->queue, &ctx->setup);
    uint8_t out[ctx->para->bits >> 3];
    RsaFillPubKey(ctx);
    ctx->opData.in_bytes = ctx->para->bits >> 3;
    ctx->opData.op_type = WCRYPTO_RSA_VERIFY;
    ctx->opData.in  = wd_alloc_blk(ctx->pool);
    ctx->opData.out = wd_alloc_blk(ctx->pool);
    memcpy(ctx->opData.in, sign, ctx->opData.in_bytes );
    wcrypto_do_rsa(ctx->rsaCtx, &ctx->opData, NULL);
    memcpy(out, ctx->opData.out, ctx->opData.out_bytes);
    for (int i = 0; i < dataLen; ++i) {
        printf("%02x %02x\n", out[i], data[i]);
    }
    wd_free_blk(ctx->pool, ctx->opData.in);
    wd_free_blk(ctx->pool, ctx->opData.out);
    wcrypto_del_rsa_ctx(ctx->rsaCtx);
    return CRYPT_SUCCESS;
}

int32_t KAE_RSA_Encrypt(KAE_RSA_Ctx* ctx, const uint8_t *data, uint32_t dataLen, uint8_t *out, uint32_t *outLen)
{
    ctx->rsaCtx = wcrypto_create_rsa_ctx(&ctx->queue, &ctx->setup);
    RsaFillPubKey(ctx);
    ctx->opData.in_bytes = ctx->para->bits >> 3;
    ctx->opData.op_type = WCRYPTO_RSA_VERIFY;
    ctx->opData.in  = wd_alloc_blk(ctx->pool);
    ctx->opData.out = wd_alloc_blk(ctx->pool);
    memcpy(ctx->opData.in, data, ctx->opData.in_bytes );
    wcrypto_do_rsa(ctx->rsaCtx, &ctx->opData, NULL);
    memcpy(out, ctx->opData.out, ctx->opData.out_bytes);
    *outLen = ctx->opData.out_bytes;
    wd_free_blk(ctx->pool, ctx->opData.in);
    wd_free_blk(ctx->pool, ctx->opData.out);
    wcrypto_del_rsa_ctx(ctx->rsaCtx);
    return CRYPT_SUCCESS;
}


int32_t KAE_RSA_Decrypt(KAE_RSA_Ctx* ctx, const uint8_t *data, uint32_t dataLen, uint8_t *out, uint32_t *outLen)
{
    ctx->rsaCtx = wcrypto_create_rsa_ctx(&ctx->queue, &ctx->setup);
    RsaFillPubKey(ctx);
    ctx->setup.is_crt ? RsaFillPrvKeyCRT(ctx) : RsaFillPrvKeyNoCRT(ctx);

    ctx->opData.in_bytes = ctx->para->bits >> 3;
    ctx->opData.op_type = WCRYPTO_RSA_SIGN;
    ctx->opData.in  = wd_alloc_blk(ctx->pool);
    ctx->opData.out = wd_alloc_blk(ctx->pool);
    memcpy(ctx->opData.in, data, ctx->opData.in_bytes );
    wcrypto_do_rsa(ctx->rsaCtx, &ctx->opData, NULL);
    memcpy(out, ctx->opData.out, ctx->opData.out_bytes);
    *outLen = ctx->opData.out_bytes;
    wd_free_blk(ctx->pool, ctx->opData.in);
    wd_free_blk(ctx->pool, ctx->opData.out);
    wcrypto_del_rsa_ctx(ctx->rsaCtx);
    return CRYPT_SUCCESS;
}

void KAE_RSA_Free(KAE_RSA_Ctx* ctx)
{
    if (ctx == NULL) {
        return ;
    }
    wd_release_queue(&(ctx->queue));
    wd_blkpool_destroy(ctx->pool);
    KAE_RSA_FreePara(ctx->para);
    free(ctx);
}

int32_t KAE_RSA_Sign(KAE_RSA_Ctx *ctx, int32_t algId, const uint8_t *data, uint32_t dataLen, uint8_t *sign, uint32_t *signLen)
{
    uint8_t hash[64];
    uint32_t hashLen = sizeof(hash) / sizeof(hash[0]);
    int32_t ret = CRYPT_EAL_Md(algId, data, dataLen, hash, &hashLen);
    if (ret != CRYPT_SUCCESS) {
        BSL_ERR_PUSH_ERROR(ret);
        return ret;
    }
    return KAE_RSA_SignData(ctx, hash, hashLen, sign, signLen);
}

int32_t KAE_RSA_Verify(KAE_RSA_Ctx *ctx, int32_t algId, const uint8_t *data, uint32_t dataLen, uint8_t *sign, uint32_t signLen)
{
    uint8_t hash[64];
    uint32_t hashLen = sizeof(hash) / sizeof(hash[0]);
    int32_t ret = CRYPT_EAL_Md(algId, data, dataLen, hash, &hashLen);
    if (ret != CRYPT_SUCCESS) {
        BSL_ERR_PUSH_ERROR(ret);
        return ret;
    }
    return KAE_RSA_VerifyData(ctx, hash, hashLen, sign, signLen);
}


